#include "Image.h"
#include <cmath>
Image::Image(std::string file)
{
    bitmap= FreeImage_Load(FIF_PNG, file.c_str());
    height = FreeImage_GetHeight(bitmap);

    width = FreeImage_GetWidth(bitmap);
    pitch = FreeImage_GetPitch(bitmap);

    red = new double *[height];
    green = new double *[height];
    blue = new double *[height];

    Y= new double *[height];
    Cb= new double *[height];
    Cr= new double *[height];

    for(int i=0; i< height; i++)
    {
        Y[i]= new double [width];
        Cb[i]= new double [width];
        Cr[i]= new double [width];

        red[i]=new double [width];
        green[i]=new double [width];
        blue[i]=new double [width];
    }
}

void Image::separateColor()
{
    FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(bitmap);
    if((image_type == FIT_BITMAP) && (FreeImage_GetBPP(bitmap) == 24))
    {
        BYTE *bits = (BYTE*)FreeImage_GetBits(bitmap);
        for(int y = 0; y < height; y++)
        {
            BYTE *pixel = (BYTE*)bits;
            for(int x = 0; x < width; x++)
            {
                red[y][x]=pixel[FI_RGBA_RED]-128;
                green[y][x]=pixel[FI_RGBA_GREEN]-128;
                blue[y][x]=pixel[FI_RGBA_BLUE]-128;
                pixel += 3;
            }
            // next line
            bits += pitch;
        }
    }
}

void Image::rgbToYCbCr()
{
    FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(bitmap);

    if((image_type == FIT_BITMAP) && (FreeImage_GetBPP(bitmap) == 24))
    {
        BYTE *bits = (BYTE*)FreeImage_GetBits(bitmap);
        for(int y = 0; y < height; y++)
        {
            BYTE *pixel = (BYTE*)bits;
            for(int x = 0; x < width; x++)
            {

                int r=pixel[FI_RGBA_RED]-128;
                int g=pixel[FI_RGBA_GREEN]-128;
                int b=pixel[FI_RGBA_BLUE]-128;

                //Y = 0.299R + 0.587G + 0.114B

                //U'= (B-Y)*0.565

                //V'= (R-Y)*0.713

                Y[y][x]=static_cast<double>(0.299*r + 0.587*g + 0.114*b);//static_cast<double>(std::floor((r+2.0*g+b )/4.0));//0.299*r+0.587*g+0.114*b;
                Cb[y][x]=static_cast<double>((b-Y[y][x])*0.565);//static_cast<double>(b-g);//-0.169*r-0.331*g+0.499*b+128;
                Cr[y][x]=static_cast<double>((r-Y[y][x])*0.713);//static_cast<double>(r-g);//0.499*r-0.418*g-0.0813*b+128;
                pixel += 3;
            }
            // next line
            bits += pitch;
        }
    }
}

void Image::YCbCrToRgb(int width, int height)
{

    std::cout<<"start conwert to rgb"<<std::endl;

    for(int y=0; y<height;++y)
    {
        for(int x=0; x<width; ++x)
        {

           // R = Y + 1.403V'

          //  G = Y - 0.344U' - 0.714V'

         //   B = Y + 1.770U'


            int r =Y[y][x] + 1.403*Cr[y][x] ;//(int)(Y[y][x]-std::floor((Cb[y][x] + Cr[y][x]) / 4.0));
            int g =Y[y][x] - 0.344*Cb[y][x] - 0.714*Cr[y][x];//(int)(Cr[y][x] + r);
            int b =Y[y][x] + 1.770*Cb[y][x] ;//(int)(Cb[y][x] + r);


            red[y][x]=static_cast<unsigned char>(Image::cat(r+128));
            green[y][x]=static_cast<unsigned char>(Image::cat(g+128));
            blue[y][x]=static_cast<unsigned char>(Image::cat(b+128));
        }
    }
}

